#!/usr/bin/env bash
# Script to register the nodes in postgres
CUR_PATH="$(dirname "${BASH_SOURCE[0]}")"

# shellcheck source=./common.sh
source "${CUR_PATH}/common.sh"

# shellcheck source=./initialize_env_dependencies
source "${CUR_PATH}/initialize_env_dependencies"

if [ "${PORT_WAIT_INTERVAL}" = "" ]; then
  PORT_WAIT_INTERVAL=3
fi

TARGET_HOST=$PG_HOST

function wait_for_postgres() {
  while true; do
    pg_isready -h "${TARGET_HOST}" &>/dev/null
    if [ $? -eq 0 ]; then
      break
    else
      log:info "Waiting for database to be ready.."
      sleep "${PORT_WAIT_INTERVAL}"
    fi
  done
}

log:info "Registering cluster nodes on ${POD_NAME}.."

function register_node() {
  local LOCAL_NODE_TYPE=$1
  local LOCAL_NODE_IDX=$2
  case "${LOCAL_NODE_TYPE}" in
  datanode)
    NODE_HOST="${KB_CLUSTER_NAME}-dn-${LOCAL_NODE_IDX}"
    NODE_NAME="dn_${LOCAL_NODE_IDX}"
    ;;
  coordinator)
    NODE_HOST="${KB_CLUSTER_NAME}-cn-${LOCAL_NODE_IDX}"
    NODE_NAME="cn_${LOCAL_NODE_IDX}"
    ;;
  *)
    assert 1 "Register node is defined only for datanodes and coordinators" || exit $?
    ;;
  esac

  wait_for_postgres || return $?

  while true; do
    LOCAL_HOST_IP=$(getent hosts "${NODE_HOST}" | awk '{ print $1 }')
    if [ -z "${LOCAL_HOST_IP}" ]; then
      log:info "Waiting for host to be ready @ ${NODE_HOST} ..."
      sleep "${PORT_WAIT_INTERVAL}"
    else
      break
    fi
  done

  log:info "Resolved ${NODE_HOST} -> ${LOCAL_HOST_IP}, registering node on local as ${LOCAL_NODE_TYPE}:"

  local CREATE_SCRIPT="CREATE NODE $NODE_NAME WITH (TYPE = '${LOCAL_NODE_TYPE}', HOST = '${NODE_HOST}', PORT = ${PG_PORT});"
  log:script "$CREATE_SCRIPT"
  psql -h "$TARGET_HOST" -c "$CREATE_SCRIPT" || true
  local ALTER_SCRIPT="ALTER NODE $NODE_NAME WITH (TYPE = '${LOCAL_NODE_TYPE}', HOST = '${NODE_HOST}', PORT = ${PG_PORT});"
  log:script "$ALTER_SCRIPT"
  psql -h "$TARGET_HOST" -c "$ALTER_SCRIPT" || true
  #  assert_warn $? "Failed executing sql script. Is node already defined? Node register skipped."
}

function register_all_dn() {
  for i in $(seq "0" "${DATANODE_COUNT}"); do
    if [ "${i}" -eq "${DATANODE_COUNT}" ]; then break; fi
    register_node datanode "${i}"
    assert $? "Failed to register datanodes" || return $?
  done
}

function register_all_cn() {
  for i in $(seq "0" "${COORDINATOR_COUNT}"); do
    if [ "${i}" -eq "${COORDINATOR_COUNT}" ]; then break; fi
    register_node coordinator "${i}"
    assert $? "Failed to register coordinator" || return $?
  done
}

function main() {
  # must be in a function so it can be called in parallel
  # (will not affect main script)

  export PGDATABASE=postgres

  # traverse all datanodes and register all datanodes and coordinators on every node.
  for n in $(seq "0" "${DATANODE_COUNT}"); do
    if [ "${n}" -eq "${DATANODE_COUNT}" ]; then break; fi
    TARGET_HOST="${KB_CLUSTER_NAME}-dn-$n"
    log:info "target host: ${TARGET_HOST}"
    register_all_dn
    register_all_cn
  done

  # traverse all coordinators and register all datanodes and coordinators on every node.
  for n in $(seq "0" "${COORDINATOR_COUNT}"); do
    if [ "${n}" -eq "${COORDINATOR_COUNT}" ]; then break; fi
    TARGET_HOST="${KB_CLUSTER_NAME}-cn-$n"
    log:info "target host: ${TARGET_HOST}"
    register_all_dn
    register_all_cn
  done

  log:info "Reloading pool...  "
  psql -q -c "SELECT pgxc_pool_reload();"
  assert $? "Failed to reload node pool" || return $?
  log:info "Registered node list:  "
  psql -q -c "SELECT * FROM pgxc_node"
  assert $? "Failed to reload node pool" || return $?

  log:info "Setting state to active."
  echo "$(date)" >> ~/service_activation_time
  assert $? "Failed generate activation file stamp" || return $?
  log:info "Node ready."
}

main
